import requests
import datetime
import time
import json
import os
import logging
import sys
import pandas as pd
import threading
from socket import *

# config读取
config = json.loads(open(r'checkConfig.json', encoding='utf-8').read())
# 消息推送
HOST = config["sendIP"]
PORT = config["sendPort"]
# 监控ID
monitor = config["monitor"]
if monitor == -1:
    sys.exit(0)
ADDR = (HOST, PORT)
thisPath = os.getcwd()
tomcats = None
times = {}

# 创建一个logger
logger = logging.getLogger('listen')
logger.setLevel(logging.DEBUG)

# 创建一个handler，用于写入日志文件
fh = logging.FileHandler('see.log')
fh.setLevel(logging.DEBUG)

# 定义handler的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)

# 给logger添加handler
logger.addHandler(fh)


# 启动tomcat
def startTomcat(path):
    os.chdir(path + "\\bin")
    os.system(".\\startup.bat")


# 根据端口干掉
def kill_port(port):
    find_port = 'netstat -aon | findstr 0.0.0.0:%s | findstr LISTENING' % port
    result = os.popen(find_port)
    info = result.read().split('\n')
    data = []
    for line in info:
        if not line:
            continue
        temp = [str for str in line.split(" ") if str]
        data.append(temp)
    parser_cmd(data)


# 干掉他！！！
def parser_cmd(data):
    columns = ["type", "secret", "open", "status", "pid"]
    df = pd.DataFrame(data=data, columns=list(columns))
    for index in range(len(data)):
        pid = df.loc[index, 'pid']
        kill_pid(pid)


# 根据PID干掉
def kill_pid(pid):
    find_kill = 'taskkill -f -pid %s' % pid
    result = os.popen(find_kill)


# 关闭tomcat
def stopTomcat(path):
    os.chdir(path + "\\bin")
    os.system(".\\shutdown.bat")


# 检查系统是否还存活 true 还存活， false 已经关闭
def checkWeb(name, checkUrl):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'}
        response = requests.post(url=checkUrl, data={}, timeout=2, headers=headers)  # 请求超时时间为2秒
        code = response.status_code  # http请求的返回状态，若为200则表示请求成功,返回的状态码是 int类型
        if code == 200:
            return True
        else:
            return False
    except:
        return False


# 获取时间
def getDate():
    today = datetime.date.today()
    return today


# 读取Tomcat监控的配置
def readTomcatConfig():
    file = open(r'checkConfig.json', encoding='utf-8')
    res = file.read()
    global tomcats
    tomcats = json.loads(res)["tomcat"]


def sendMSG(msg):
    try:
        tcpCliSock = socket(AF_INET, SOCK_STREAM)
        tcpCliSock.connect(ADDR)
        data = {"type": "forward", "monitor": monitor, "msg": msg}
        tcpCliSock.send(str(data).encode())
        tcpCliSock.close()
    except Exception as r:
        logger.error(str(r) + '--------sendMSG')
        print('请求失败，继续请求')


# 主函数
def mainApp():
    readTomcatConfig()
    for item in tomcats:
        if item["name"] not in times:
            times[item["name"]] = 1
        if not checkWeb(item["name"], item["checkUrl"]):
            sendMSG('**' + item["name"] + "** \n\nTomcat出现访问错误 \n - 第" + str(times[item["name"]]) + "次 \n\n 两次后自动重启")
            if times[item["name"]] >= 2:
                kill_port(item["port"])
                time.sleep(2)
                startTomcat(item["tomcatPath"])
                restartTimes = 0
                while True:
                    if checkWeb(item["name"], item["checkUrl"]):
                        sendMSG('**' + item["name"] + "** \n- Tomcat已重启")
                        times[item["name"]] = 1
                        break
                    else:
                        restartTimes += 1
                        sendMSG('**' + item["name"] + "** \n- 重启后暂未启动完成")
                        maxRestart = 60
                        if restartTimes > maxRestart:
                            sendMSG('**' + item["name"] + "** \n- 重启后" + str(maxRestart * 3) + '秒未重启成功，尝试重新启动')
                            times[item["name"]] = times[item["name"]] + 1
                            break
                        time.sleep(3)
                os.chdir(thisPath)
            else:
                times[item["name"]] = times[item["name"]] + 1
        else:
            times[item["name"]] = 1


# start 方法
def start():
    try:
        do = threading.Thread(target=mainApp, )
        do.start()
        while do.is_alive():
            time.sleep(0.5)
    except Exception as r:
        logger.error(str(r) + '--------start')
    finally:
        threading.Timer(10, start, ()).start()


def selfHeart():
    try:
        tcpCliSock = socket(AF_INET, SOCK_STREAM)
        tcpCliSock.connect(ADDR)
        data = {"type": "heart", "monitor": monitor}
        tcpCliSock.send(str(data).encode())
        tcpCliSock.close()
    except Exception as r:
        logger.error(str(r) + '--------selfHeart')
    finally:
        threading.Timer(60, selfHeart, ()).start()


threading.Thread(target=selfHeart, ).start()
start()
sendMSG('**TOMCAT 存活状态监测脚本启动**')
